
#ifndef LDAC_DEC_PRIV_LIB_H
#define LDAC_DEC_PRIV_LIB_H

#define ENABLE_BUFFER_CONTROL


/****************************************************************************
Private Definitions Macro for Debug
*/







/****************************************************************************
Include files
*/
#include "mem_utils/memory_table.h"
#include "mem_utils/shared_memory_ids.h"
#include "mem_utils/scratch_memory.h"
#include "capabilities.h"
#include "ldac_buffer_control.h"

/* LDAC handle type */
typedef struct _st_ldacbt_handle * HANDLE_LDAC_BT;
#ifndef LDACBT_API
#define LDACBT_API
#endif /* LDACBT_API  */
LDACBT_API HANDLE_LDAC_BT ldacBT_get_handle( HANDLE_LDAC_BT hLdacBT,int cm );
LDACBT_API int ldacBT_init_handle_decode( HANDLE_LDAC_BT hLdacBt, int cm, int sf,
                                          int var0, int var1, int var2 );

LDACBT_API int ldacBT_decode_S32( HANDLE_LDAC_BT hLdacBT, unsigned char *p_bs,
                              unsigned char *p_pcm0, unsigned char *p_pcm1,
                              int bs_bytes, int *used_bytes, int *wrote_bytes );

LDACBT_API int  ldacBT_get_error_code( HANDLE_LDAC_BT hLdacBt );

/* Support for MONO */
#define LDACBT_CHANNEL_MODE_MONO           0x04
/* Support for DUAL CHANNEL */
#define LDACBT_CHANNEL_MODE_DUAL_CHANNEL   0x02
/* Support for STEREO */
#define LDACBT_CHANNEL_MODE_STEREO         0x01

/****************************************************************************
Constant Definitions
*/

/** Terminal numbers */
#define LEFT_OUT_TERMINAL_ID            0
#define RIGHT_OUT_TERMINAL_ID           1
#define INPUT_TERMINAL_ID               (0 | TERMINAL_SINK_MASK)


#define PCM_ADJUST	//this macro is to prevent to running out pcm buffer of src sync 
#undef PCM_ADJUST_MORE	//this macro is to prevent to running out pcm buffer of src sync 

#define LDAC_DECODE_VERSION_MAJOR       1
#ifdef PCM_ADJUST
#define LDAC_OUTPUT_BUFF_LENGTH                 5120         //5frames@2fs,256x4x5=5120
// #define LDAC_OUTPUT_BUFF_LENGTH                 (256*5)         //5frames@2fs,256x5=1280 in words
#else
#define LDAC_OUTPUT_BUFF_LENGTH                 2048            //2frames@2fs
#endif
//#define LDAC_OUTPUT_BUFF_LENGTH                 256
#define LDAC_TMP_BUF_SIZE                       16
#define LDAC_DEC_DM1_SCRATCH_TABLE_LENGTH       1
#define LDAC_DEC_DM2_SCRATCH_TABLE_LENGTH       1
#define ADJUST_BYTE                             10
#define MAX_LDAC_FRAME_SIZE                     (330 + ADJUST_BYTE)
#define LDAC_TABLE_LENGTH                       1
#define LDAC_DEC_MALLOC_TABLE_LENGTH            2
#define LDAC_BT_RTP_HEADER_SIZE                 12

#define LDAC_RXBUF_MAIN_SIZE                    (32*1024)
#define LDAC_RXBUF_CARRIED_SIZE                    (1024)

#define LDAC_BUFFER_CONT_STS_BUF_SIZE           200
#define PCM_OUTPUT_BUFFER_SIZE                  1024

#define LDAC_DEC_SELF_KICK_RATIO 2

#define LDAC_TIMER_MASK_BITLEN 23
#define LDAC_TIMER_MAX   (1U << LDAC_TIMER_MASK_BITLEN) /*0x800000(8388608us),1s=1000000us*/
#define LDAC_TIMER_MASK  (LDAC_TIMER_MAX-1)

#ifdef PCM_ADJUST //for pcm adjust sample
#define LDAC_PCM_ADJUST_COUNT_48K   4000
#define LDAC_PCM_ADJUST_COUNT_44K   5871
#endif
/****************************************************************************
Private Type Definitions
*/
typedef struct
{
    int nFrame;
    tCbuffer *main;
    tCbuffer *clone;
    
    // for fragmented packet (not tested yet)
    tCbuffer *carried;
    int remaining_FrmNum;
    int carried_Octets;
} LDAC_DEC_RX_BUF;

typedef struct
{
    int base_us;
    int elapsed_us;
    int remained_us;
} LDAC_DEC_TIMER;

typedef struct
{
    struct buffer_control *bc;
    tCbuffer *cb_frame_sts;
} LDAC_BUFF_CTRL_OP;



typedef struct
{
    bool     playing;
    LDAC_DEC_TIMER timer;
    LDAC_DEC_RX_BUF RxBuf;
    LDAC_BUFF_CTRL_OP hBufCtrl;
    HANDLE_LDAC_BT hData;
    tCbuffer *cb_stream; // buffer to pass bitstream to decoder

    // configuration
    unsigned sampling_freq;
    unsigned channel_mode;
    unsigned frame_length_us;
    unsigned frame_length_sample;

    // information for application
    unsigned num_output_samples;
    unsigned frame_size;
    unsigned char remain_byte;
    unsigned char remain_byte_flg;
    void *tmp1;
    void *tmp2;
    unsigned char * p_pcm_out_0;
    unsigned char * p_pcm_out_1;
#ifdef PCM_ADJUST
    int adjust_frm_count;
    int adjust_frm_num;
#endif

} LDAC_DEC_PARAMS;

#ifndef ParamType
typedef unsigned ParamType;
#endif

// Statistics Block
typedef struct _tag_LDAC_DECODE_STATISTICS
{
    ParamType OFFSET_SAMPLING_FREQUENCY;
    ParamType OFFSET_CHANNEL_MODE;
    ParamType OFFSET_FRAME_SIZE;
}LDAC_DECODE_STATISTICS;


/***************************************************************************
Private Function Declarations
*/
extern malloc_t_entry ldac_malloc_table3[];
/* Scratch memory used by an encoder/decoder instance */
extern const scratch_malloc_t_entry ldac_scratch_table_dm1[];
/* Scratch memory used by an encoder/decoder instance */
extern const scratch_malloc_t_entry ldac_scratch_table_dm2[];
extern unsigned char g_ldacbt_handle[];

extern const malloc_t_entry ldac_dec_malloc_table[];

extern const scratch_table decoder_scratch_table;

extern void ldac_decode_timer_task(void *timer_data);

extern void ldac_decoder_initiliase( LDAC_DEC_PARAMS *pDecParams );
extern int ldac_decoder_stores_rx_data(tCbuffer *in_buffer, LDAC_DEC_PARAMS *pDecParams, int *nFrmRegistered );
#ifdef PCM_ADJUST_MORE
extern int ldac_decoder_get_nFrames_to_decode( LDAC_DEC_PARAMS *pDecParams, void* p_decoder_data, TIME now, int frameNumLimit );
#else
extern int ldac_decoder_get_nFrames_to_decode( LDAC_DEC_PARAMS *pDecParams, TIME now, int frameNumLimit );
#endif
extern int ldac_decoder_decode_frames( LDAC_DEC_PARAMS *pDecParams, unsigned char *p_pcm_out_0, unsigned char *p_pcm_out_1);
extern void reset_cbuffers( tCbuffer *cb );
extern void bc_mem_destroy(LDAC_BUFF_CTRL_OP *hBufCtrl);
extern int bc_mem_create(LDAC_BUFF_CTRL_OP *hBufCtrl);
extern void bc_init(LDAC_BUFF_CTRL_OP *hBufCtrl);
extern int bc_prepare(LDAC_BUFF_CTRL_OP *hBufCtrl);
extern void bc_print_sts(LDAC_BUFF_CTRL_OP *hBufCtrl);


#endif /* LDAC_DEC_PRIV_LIB_H */
